La soluzione dell'esercizio 2 non viene fornita.

Per realizzare l'esercizio una possibile soluzione e' quella di implementare una astrazione di pool di thread anonimi, attraverso le seguenti tre funzioni: 

// crea numthreads ed una coda di dimensione queueSize (se queueSize e' <0 si puo' implementare una coda di lunghezza infinita come una lista dinamica)
pool * createPool(int numthreads, int queuesize);

// implementa il protocollo di terminazione di tutti i threads ed attende la loro uscita
int destroyPool(pool *pool);

// chiede che venga eseguita la funzione fun con argomento arg da uno dei thread del pool
// in sostanza crea un task formato da <fun,arg> e lo inserisce nella coda che fa da interfaccia verso i thread workers. 
int addToPool(pool *pool, void (*fun)(void*), void *arg); 

Ogni thread del pool esegue un ciclo "infinito" in cui attende un task prelevando dalla coda ed esegue la funzione associata al task. 
La terminazione dei threads puo' essere gestita con un task speciale.

 
